package com.jc.service.userorder;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.channels.Channel;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.jc.cds.mapper.CustomerUserOrderMapper;
import com.jc.cds.model.CustomUserOrder;
import com.jc.common.util.Base64Util;
import com.jc.common.util.CommonStr;
import com.jc.common.util.DateTimeUtil;
import com.jc.common.util.HttpUtil;
import com.jc.common.util.TaskType;
import com.jc.common.util.UUIDUtil;
import com.jc.ds.base.service.BaseServiceException;
import com.jc.ds.base.service.BaseServiceImpl;
import com.jc.ds.mapper.UserOrderMapper;
import com.jc.ds.model.UserOrder;
import com.jc.ds.model.UserTask;
import com.jc.framework.enums.Booleans;
import com.jc.framework.enums.ChannelSource;
import com.jc.framework.enums.Conclusion;
import com.jc.framework.enums.GameChannel;
import com.jc.framework.enums.LogType;
import com.jc.framework.enums.OrderStatus;
import com.jc.framework.enums.OrderType;
import com.jc.service.api.appgame.model.NoticUser;
import com.jc.service.apilog.ApiLogService;
import com.jc.service.appgame.AppGameService;
import com.jc.service.chain.ChainRequestModel;
import com.jc.service.chain.ChainResult;
import com.jc.service.chain.ChainService;
import com.jc.service.gameinterface.GameInterfaceService;
import com.jc.service.gameuser.GameUserService;
import com.jc.service.usertask.UserTaskService;
import com.jc.service.uservrtaddress.UserVrtAddressService;
import com.jc.service.vrt.VrtService;
import com.jc.service.vrt.model.VrtResult;

@Service
public class UserOrderServiceImp extends BaseServiceImpl<UserOrder, CustomUserOrder, Long> implements UserOrderService {

	@Value("${withdraw.max.amount}")
	private String withdrawMaxAmountStr;

	@Value("${vrt.gamemoney.ratio}")
	private String convertRatio;

	// 平台扣除百分比
	@Value("${vrt.transfer.fee}")
	private String subvalue;

	@Value("${playfrom.gift.gamemoney}")
	private String platformGiftGameMoney;
	
	
	@Value("${playfrom.out_system_urls}")
	private String out_system_urls;
	
	@Value("${vrt.notice.ispush}")
	private String ispush;

	@Autowired
	ChainService chainService;

	@Autowired
	UserOrderService userOrderService;

	@Autowired
	GameUserService gameUserService;

	@Autowired
	UserVrtAddressService userVrtAddressService;

	@Autowired
	GameInterfaceService gameInterfaceService;

	@Autowired
	UserTaskService userTaskService;
	
	@Autowired
	ApiLogService apiLogService;

	@Autowired
	VrtService vrtService;
	
	@Autowired
	AppGameService appGameService;
	
	@Override
	public CustomerUserOrderMapper getCustomMapper() {
		return (CustomerUserOrderMapper) this.getBaseCustomMapper();
	}

	@Override
	public Boolean isWithdrawalOfExcess(Long userId, BigDecimal bigMoney) {
		BigDecimal bigDecimal = this.getCustomMapper().withdrawalOfExcess(userId);
		if (bigDecimal == null) {
			bigDecimal = new BigDecimal(0);
		}
		BigDecimal withdrawMaxAmount = new BigDecimal(withdrawMaxAmountStr);
		if (withdrawMaxAmount.compareTo(bigDecimal) >= 0) {
			BigDecimal add = bigDecimal.add(bigMoney);
			if (withdrawMaxAmount.compareTo(add) >= 0) {
				return true;
			} else {
				return false;
			}
		}
		return false;
	}

	@Transactional
	public ChainResult transfer(String coin_name, BigDecimal amount, Long send_user_id_out, Long receive_user_id_out,
			String remarks, int businessType , String channel,String channelOrderId) {
		String order_id = UUIDUtil.getUUID();
		String payer_address = userVrtAddressService.getUserVrtAddressByUserId(send_user_id_out);
		String payee_address = userVrtAddressService.getUserVrtAddressByUserId(receive_user_id_out);
		// 付款人为空
		if (StringUtils.isBlank(payer_address)) {
			throw new BaseServiceException("付款人没有配置钱包地址");
		}
		if (StringUtils.isBlank(payee_address)) {
			throw new BaseServiceException("收款人没有配置钱包地址");
		}
		if (amount.compareTo(BigDecimal.ZERO) <= 0) {
			throw new BaseServiceException("交易金额不能为0");
		}
		BigDecimal orderAmount = BigDecimal.ZERO; // 转换为VRT币的交易额

		// 充值/提现 都是以游戏币为参数传进来,在下面逻辑中换算为VRT
		orderAmount = amount.divide(new BigDecimal(convertRatio), 2, RoundingMode.DOWN);// 向下两位小数，不进行四舍五入

		// 计算平台扣除费用
		BigDecimal playfromAmount = BigDecimal.ZERO;
		if (OrderType.VRT提现.getIndex() == businessType) {// 扣除平台手续费再进行交易,先扣保证足额扣除
			playfromAmount = orderAmount.multiply(new BigDecimal(subvalue)).setScale(2, BigDecimal.ROUND_DOWN); // 向下两位小数，不进行四舍五入
		}
		
		if(StringUtils.equals(channel, GameChannel.ZHONGLE_H5.getName())) {
			//原H5渠道不扣除平台手续费
			playfromAmount = BigDecimal.ZERO;
		}
		orderAmount = orderAmount.subtract(playfromAmount).setScale(2, BigDecimal.ROUND_DOWN);
		///
		Long requestAmount = orderAmount.longValue();
		if (requestAmount == null || requestAmount < 1) {
			throw new BaseServiceException("交易金额不能为空 且必须大于 0");
		}

		ChainResult ret = chainService.transfer(coin_name, String.valueOf(requestAmount), payer_address, payee_address,
				order_id, remarks);
		if(ret != null) {
			getLOGGER().error("===================================请求区块链交易返回 : {}  ", JSONObject.toJSONString(ret) );;
		}
		if (ret != null && StringUtils.equals(CommonStr.SUCCESS, ret.getReturn_code())) {
			// 创建待处理订单
			UserOrder order = new UserOrder();
			order.setOrderId(order_id);
			order.setSendUserId(String.valueOf(send_user_id_out));
			order.setSendUserVrtAddress(payer_address);
			order.setReceiveUserId(String.valueOf(receive_user_id_out));
			order.setReceiveUserVrtAddress(payee_address);
			order.setCreateTime(new Date());
			order.setOrderStatus(OrderStatus.交易中.getIndex());
			if (OrderType.VRT提现.getIndex() == businessType) {// 提现
				order.setOrderType(OrderType.VRT提现.getIndex());
			} else {
				order.setOrderType(OrderType.VRT充值.getIndex());
			}
			
			if(!StringUtils.isBlank(channelOrderId)) {
				order.setChannelOrderId(channelOrderId);
			}
			order.setRequestAmount(orderAmount);
			order.setPlatfromTaxAmount(playfromAmount);
			order.setRequestGameMoney(amount);
			if(StringUtils.isBlank(channel)) {
				order.setChannelCode(GameChannel.ZHONGLE_H5.getName());
			}else {
				order.setChannelCode(channel);
			}
			userOrderService.add(order, false);
		}
		return ret;

	}

	public ChainResult queryBalance(Long out_user_id, String coin_name) {

		String user_vrt_address = userVrtAddressService.getUserVrtAddressByUserId(out_user_id);
		return chainService.queryBalance(coin_name, user_vrt_address);
	}

	public String transferCallBack(ChainRequestModel model) {
		if (model == null) {
			throw new BaseServiceException("参数为空");
		}
		String order_id = model.getOrder_id();
		if (StringUtils.isBlank(order_id)) {
			throw new BaseServiceException("回调函数里面的 order_id 为空");
		}
		UserOrder _order = new UserOrder();
		_order.setOrderId(order_id);
		List<UserOrder> uoList = queryAll(_order);
		if (CollectionUtils.isEmpty(uoList)) {
			throw new BaseServiceException(order_id + "这笔转账订单,不存在");
		}
		UserOrder uo = uoList.get(0);

		// update order status
		if (StringUtils.isNotBlank(model.getOrder_state())	&& StringUtils.equals(CommonStr.SUCCESS, model.getOrder_state())) {
			uo.setOrderStatus(OrderStatus.交易成功.getIndex());
			modify(uo, false);
			// push game server
			BigDecimal gameMoney = uo.getRequestGameMoney();
			if (uo.getOrderType() == OrderType.VRT充值.getIndex()) {
				if (StringUtils.isNotBlank(platformGiftGameMoney)) {
					gameMoney = gameMoney.add(new BigDecimal(platformGiftGameMoney));
				} else {
					gameMoney = gameMoney.add(new BigDecimal("100"));
				}
				//调用游戏充值接口
				Map<String, Object> retMap = null;
				//增加游戏币
				if(StringUtils.isBlank(uo.getChannelCode())) {
					retMap = gameInterfaceService.rechargeOrWithdraw(Long.valueOf(uo.getSendUserId()),gameMoney);
				}else {
					//GameChannel.ZHONGLE_H5.getName()
					switch (uo.getChannelCode()) {
						case "ZHONGLE_H5":
							retMap = gameInterfaceService.rechargeOrWithdraw(Long.valueOf(uo.getSendUserId()),gameMoney);
							break;
						case "SHENYANG_APP_GAME":
							NoticUser ncUser = new NoticUser();
							ncUser.setUserId(Long.valueOf(uo.getSendUserId()));
							ncUser.setOrderId(uo.getChannelOrderId());
							ncUser.setAmount(gameMoney.longValue());
							ncUser.setState(1);//交易成功
							appGameService.noticAppGame(ncUser);
							break;
					}
				}
				
				//处理充值金币结果
				if (retMap == null || retMap.size() == 0 || retMap.get("success") == null
						|| !StringUtils.equals(retMap.get("success").toString(), "1")) {
					Map<String, Object> dataMap = new HashMap<String, Object>();
					dataMap.put("gameMoney", gameMoney);
					dataMap.put("userId", uo.getSendUserId());
					userTaskService.addTask(TaskType.ADD_GAME_MONEY, JSONObject.toJSONString(dataMap), uo.getOrderId(), Booleans.FALSE, null);
				}

			} else if (uo.getOrderType() == OrderType.VRT提现.getIndex()) {//提现无操作
				//判断是APP游戏的渠道订单需要回调游戏
				if(StringUtils.isNotBlank(uo.getChannelCode()) && StringUtils.equals(GameChannel.SHENYANG_APP_GAME.getName(), uo.getChannelCode())) {
					NoticUser ncUser = new NoticUser();
					ncUser.setUserId(Long.valueOf(uo.getReceiveUserId()));
					ncUser.setOrderId(uo.getChannelOrderId());
					ncUser.setAmount(gameMoney.longValue());
					ncUser.setState(1);//交易成功
					appGameService.noticAppGame(ncUser);
				}
				
				
			}
			
			// 通知第三方系统
			//String isNotice = "push";
			
			if(StringUtils.equals(ispush, "push")) {				
				// begin prepare notice data
				Map<String,Object> noticeMap = new HashMap<String,Object>();
				//recharge : 充值 cashwithdrawal: 提现
				
				if (uo.getOrderType() == OrderType.VRT提现.getIndex()) {
					noticeMap.put("orderType", "cashwithdrawal");
				}else {
					noticeMap.put("orderType", "recharge");
				}
				noticeMap.put("userId",uo.getSendUserId());
				noticeMap.put("businessType","game");
				noticeMap.put("time",DateTimeUtil.getDate(DateTimeUtil.LONG_TIME_FORMAT));
				noticeMap.put("amount",gameMoney);
				noticeMap.put("orderId", uo.getOrderId());
				getLOGGER().error(">>>>>>>>>>>>>>>开始通知VRT社区充值成功..................................................................................................................................................." + uo.getOrderId());
				VrtResult result = vrtService.pushVrtClub(noticeMap, "/saveGameChargeLog" , LogType.NOTICE_VRT_CLUB);
				//这里不做业务判断，接口请求日志里面记录了请求成功失败
			}
			apiLogService.addApiLog(LogType.CHAIN_CALL_BACK, JSONObject.toJSONString(model), Conclusion.OK, "交易成功" , CommonStr.SUCCESS);
		} else {
			
			uo.setOrderStatus(OrderStatus.交易失败.getIndex());
			modify(uo, false);
			/**********提现失败把之前扣掉用户的金币推送到游戏服务器加到用户账户上面 *************/
			if(uo.getOrderType() == OrderType.VRT提现.getIndex()) {
				//增加游戏币
				if(StringUtils.isBlank(uo.getChannelCode())) {
					Map<String, Object> retMap = gameInterfaceService.rechargeOrWithdraw(Long.valueOf(uo.getReceiveUserId()), uo.getRequestGameMoney() );
					if (retMap == null || retMap.size() == 0 || retMap.get("success") == null || !StringUtils.equals(retMap.get("success").toString(), "1")) {
						userTaskService.addTask(TaskType.ADD_GAME_MONEY, uo.getOrderId(), uo.getOrderId(), Booleans.FALSE, null);
					}
				}else {
					//GameChannel.ZHONGLE_H5.getName()
					switch (uo.getChannelCode()) {
						case "ZHONGLE_H5":
							Map<String, Object> retMap = gameInterfaceService.rechargeOrWithdraw(Long.valueOf(uo.getReceiveUserId()), uo.getRequestGameMoney() );
							if (retMap == null || retMap.size() == 0 || retMap.get("success") == null || !StringUtils.equals(retMap.get("success").toString(), "1")) {
								userTaskService.addTask(TaskType.ADD_GAME_MONEY, uo.getOrderId(), uo.getOrderId(), Booleans.FALSE, null);
							}
							break;
						case "SHENYANG_APP_GAME":
							//调用APP 游戏增加金币
							NoticUser ncUser = new NoticUser();
							ncUser.setUserId(Long.valueOf(uo.getReceiveUserId()));
							ncUser.setOrderId(uo.getChannelOrderId());
							ncUser.setAmount(uo.getRequestGameMoney().longValue());
							ncUser.setState(0);//交易失败
							appGameService.noticAppGame(ncUser);
							break;
					}
				}
			
			}else {
				//判断是APP游戏的渠道订单需要回调游戏
				if(StringUtils.isNotBlank(uo.getChannelCode()) && StringUtils.equals(GameChannel.SHENYANG_APP_GAME.getName(), uo.getChannelCode())) {
					NoticUser ncUser = new NoticUser();
					ncUser.setUserId(Long.valueOf(uo.getSendUserId()));
					ncUser.setOrderId(uo.getChannelOrderId());
					ncUser.setAmount(uo.getRequestGameMoney().longValue());
					ncUser.setState(0);//交易失败
					appGameService.noticAppGame(ncUser);
				}
			}
			
		//记录日志 api_log
		apiLogService.addApiLog(LogType.CHAIN_CALL_BACK, JSONObject.toJSONString(model), Conclusion.FAIL, "交易失败" , CommonStr.SUCCESS);
	  }
		
	  return CommonStr.SUCCESS;
	}

	public static void main(String[] args) {
		String s ="{\"head\":\"TzhENm45UkZoeDJ3ZnhCM3ZuUm0xWk5Wbnk2eVhxaTdLYkt0WDl2eHdoaTFWMENnNks5UjFhNUZZdC9DcHNRbStwc3lEVE1qdDdxUXE1SHd1UDdCcjBFbHNVSUt5K0VPTmtUamtnbXBXNVU9\",\"amount\":\"S3pnYlBVaURrZVN4ejMxcHc2WGdvUT09\",\"name\":\"WWZjU2diTlFkM000ZDZoakhmdG94dz09\",\"userId\":\"dGpSK3RZWTF4enlmZ2RzRUtidXFsdz09\"}";

		Map a = JSONObject.parseObject(s,Map.class);
		System.out.println(a);
		
		
		
		Map<String,Object> noticeMap = new HashMap<String,Object>();
		noticeMap.put("userId","62100");
		noticeMap.put("addr","DFADF44F5FAD11df4D4FDdf");
		noticeMap.put("time",DateTimeUtil.getDate(DateTimeUtil.LONG_TIME_FORMAT));
		noticeMap.put("amount",1000);
		noticeMap.put("transactionId", "2015441");
		System.out.println(JSONObject.toJSONString(noticeMap));
		

	}

	public List<CustomUserOrder> queryOrderAllUser(UserOrder userOrder) {
		List<CustomUserOrder> list = this.getCustomMapper().queryOrderAllUser(userOrder);
		return list;
	}

}
